#ifndef __INKLUDE_C_UDP_CLIENT_H__
#define __INKLUDE_C_UDP_CLIENT_H__

#include <Inklude/Inklude.h>
#include <Inklude/ikINetClient.h>
#include <memory>

namespace Inklude
{
    namespace Internal
    {
        class ikCUdpBoost;
    }

    enum INKLUDE_UDP
    {
        IK_UDP_NON_BLOCKING = 0,
        IK_UDP_BLOCKING = 1
    };


    class INKLUDE_CLASS_EXPORT ikCUdpClient
    {
    public:
        typedef std::shared_ptr<std::function<void (size_t)> > AsyncHandler;

        ikCUdpClient();
        virtual ~ikCUdpClient() {}
        void Initialize(unsigned int nRecvPort = 0);
        void SetDestinationAddress(const char* IPAddress, unsigned int nPort);
        size_t Send(void* pBuffer, size_t nDataSize);
        size_t Receive(void* pBuffer, size_t nDataSize);

        void AsyncSend(void* pBuffer, size_t nDataSize, AsyncHandler endHandler);
        void AsyncReceive(void* pBuffer, size_t nDataSize, AsyncHandler endHandler);

    protected:
        void _init();

    private:
        int m_nPort;
        std::shared_ptr<Inklude::Internal::ikCUdpBoost> m_pUdp;
    };

    typedef std::shared_ptr<ikCUdpClient> ikCUdpClientPtr;

    class INKLUDE_CLASS_EXPORT ikCUdpClientAsync : public ikINetClient
    {
    public:
        ikCUdpClientAsync() : m_pUdp(new ikCUdpClient) {}
        virtual ~ikCUdpClientAsync() {}
        virtual void Initialize(unsigned int nRecvPort = 0);
        virtual void SetDestinationAddress(const char* IPAddress, unsigned int nPort);
        virtual size_t Send(const void* pBuffer, size_t nDataSize, AsyncHandler endHandler = NULL);
        virtual size_t Receive(void* pBuffer, const size_t nDataSize, AsyncHandler endHandler = NULL);
        virtual void Close() {}

    private:
        std::shared_ptr<Inklude::ikCUdpClient> m_pUdp;
    };

    class INKLUDE_CLASS_EXPORT ikCUdpClientSync : public ikINetClient
    {
    public:
        ikCUdpClientSync() : m_pUdp(new ikCUdpClient) {}
        virtual ~ikCUdpClientSync() {}
        virtual void Initialize(unsigned int nRecvPort);
        virtual void SetDestinationAddress(const char* IPAddress, unsigned int nPort);
        virtual size_t Send(const void* pBuffer, size_t nDataSize, AsyncHandler endHandler = NULL);
        virtual size_t Receive(void* pBuffer, const size_t nDataSize, AsyncHandler endHandler = NULL);
        virtual void Close() {}

    private:
        std::shared_ptr<Inklude::ikCUdpClient> m_pUdp;
    };

    typedef std::shared_ptr<std::function<void (size_t)> > ikAsyncHandler;
}


#endif // __INKLUDE_C_UDP_CLIENT_H__

